import GussainBlur from "./GussainBlur/GussainBlur";

const { ccclass, property } = cc._decorator;

const enum BaseMats {
    Base = 0,
    Blur,
};

@ccclass
export default class CaptureMask extends cc.Component {

    @property(cc.Camera)
    camera: cc.Camera = null;
    @property(cc.Sprite)
    captureSpr: cc.Sprite = null;
    @property(cc.Node)// load on World UI ...
    rootNode: cc.Node = null;
    @property// capture texture assemble ratio, to decrease shader calc times
    captureRatio: number = 1;

    @property
    alignWinCenter: boolean = false;

    @property
    once: boolean = true;

    @property
    useBlur: boolean = false;

    @property([cc.Material])
    baseMats: cc.Material[] = [];

    _lastCaptureTexture: cc.RenderTexture = null;
    _lastSpriteFrame: cc.SpriteFrame = null;

    onLoad() {
    }

    onEnable() {
        this.scheduleOnce(() => {
            this.once ? this.doCapture() : this.alwaysCapture();
        });
        if (this.camera) {
            this.camera.clearFlags = cc.Camera.ClearFlags.COLOR | cc.Camera.ClearFlags.DEPTH | cc.Camera.ClearFlags.STENCIL;
            this.camera.backgroundColor = cc.color(0, 0, 0, 0);
        }
    }

    onDisable() {
        // this.rootNode.active = true;
        this.rootNode.opacity = 255;
    }

    resetPosition() {
        this.alignWinCenter && this.node.setPosition(cc.winSize.width * .5, cc.winSize.height * .5);
    }

    doCapture() {
        // cc.log("doCapture");
        this.resetPosition();
        const width = cc.winSize.width, height = cc.winSize.height;
        if (cc.isValid(this._lastCaptureTexture)) this._lastCaptureTexture.destroy();
        if (cc.isValid(this._lastSpriteFrame)) this._lastSpriteFrame.destroy();
        this.captureSpr.spriteFrame = null;
        let captureTexture = new cc.RenderTexture();
        captureTexture.initWithSize(width / this.captureRatio, height / this.captureRatio, (cc.game as any)._renderContext.STENCIL_INDEX8);
        this._lastCaptureTexture = captureTexture;
        this.camera.targetTexture = captureTexture;
        this.camera.node.active = true;
        // this.rootNode.active = true;
        this.rootNode.opacity = 255;
        this.camera.render(this.rootNode);
        // this.rootNode.active = false;
        this.rootNode.opacity = 0;
        this.camera.node.active = false;
        this.camera.targetTexture = null;
        this.captureSpr.spriteFrame = new cc.SpriteFrame(captureTexture);
        this._lastSpriteFrame = this.captureSpr.spriteFrame;
        if (this.once && this.useBlur) {
            this.captureSpr.setMaterial(0, this.baseMats[BaseMats.Blur]);
            this.captureSpr.getMaterial(0).setProperty("textureSize", cc.v2(width, height));
            this.captureSpr.node.getComponent(GussainBlur).updateBlur();
            let blurHandler = this.node.getComponent(GussainBlur);
            this.scheduleOnce(() => {
                this.scheduleOnce(() => {
                    let lastRoot = this.rootNode;
                    this.rootNode = this.node;
                    let tmpRenderTexture = new cc.RenderTexture();
                    tmpRenderTexture.initWithSize(width / this.captureRatio, height / this.captureRatio, (cc.game as any)._renderContext.STENCIL_INDEX8);
                    this.camera.targetTexture = tmpRenderTexture;
                    this.camera.node.active = true;
                    this.camera.render(this.rootNode);
                    this.camera.targetTexture = null;
                    this.camera.node.active = false;
                    this.captureSpr.spriteFrame = new cc.SpriteFrame(tmpRenderTexture);
                    this.captureSpr.setMaterial(0, this.baseMats[BaseMats.Base]);
                    this._lastCaptureTexture.destroy();
                    this._lastSpriteFrame.destroy();
                    this._lastCaptureTexture = tmpRenderTexture;
                    this._lastSpriteFrame = this.captureSpr.spriteFrame;
                    this.rootNode = lastRoot;
                })
            }, blurHandler ? blurHandler.dura : 0);
        }
        this.captureSpr.node.scaleY = -this.captureRatio;
    }

    alwaysCapture() {
        cc.log("alwaysCapture");
        this.resetPosition();
        const width = cc.winSize.width, height = cc.winSize.height;
        if (cc.isValid(this._lastCaptureTexture)) this._lastCaptureTexture.destroy();
        if (cc.isValid(this._lastSpriteFrame)) this._lastSpriteFrame.destroy();
        this.captureSpr.spriteFrame = null;
        let captureTexture = new cc.RenderTexture();
        captureTexture.initWithSize(width / this.captureRatio, height / this.captureRatio, cc.RenderTexture.DepthStencilFormat.RB_FMT_D24S8);
        this._lastCaptureTexture = captureTexture;
        this.camera.targetTexture = captureTexture;
        this.camera.node.active = true;
        // this.rootNode.active = true;
        // this.rootNode.opacity = 255;
        this.camera.render(this.rootNode);
        // this.rootNode.active = false;
        // this.rootNode.opacity = 0;
        // this.camera.node.active = false;
        // this.camera.targetTexture = null;
        this.captureSpr.spriteFrame = new cc.SpriteFrame(captureTexture);
        this._lastSpriteFrame = this.captureSpr.spriteFrame;
        this.captureSpr.node.scaleY = -this.captureRatio;
        if (this.useBlur) {
            this.captureSpr.setMaterial(0, this.baseMats[BaseMats.Blur]);
            this.captureSpr.getMaterial(0).setProperty("textureSize", cc.v2(width, height));
            this.captureSpr.node.getComponent(GussainBlur).updateBlur();
        }
    }
}
